#ifndef __GLF_TASK_TASKHANDLER_IMPL_H_INCLUDED__
#define __GLF_TASK_TASKHANDLER_IMPL_H_INCLUDED__

#include <glf/task/taskHandler.h>
#include <glf/core/inlines.h>
#include <glf/core/syncEvent.h>
#include <glf/task/taskCondition.h>
#include <glf/task/task.h>
#include <glf/task/taskDirector.h>
#include <glf/task/taskManager.h>
#include <glf/core/spinLock.h>
#include <glf/core/atomic.h>
#include <glf/core/threadTraits.h>

namespace glf {

template<typename Tag>
TaskHandlerImpl<Tag>::Working::Working(TaskManager& tm)
: m_Tm(tm)
{
	m_Tm.StartWork();
}

template<typename Tag>
TaskHandlerImpl<Tag>::Working::~Working()
{
	m_Tm.EndWork();
}


template<typename Tag>
TaskHandlerImpl<Tag>::TaskHandlerImpl(TaskCondition* tc)
	: m_TaskCondition(tc)
	, m_AttachedToThread(0)
	, m_RegisteredThreadId(0)
{
	if(tc)
	{
		TaskManager::GetInstance<Tag>().AddTaskCondition(tc);
		tc->AddTaskManager(&TaskManager::GetInstance<Tag>());
	}
}

template<typename Tag>
TaskHandlerImpl<Tag>::~TaskHandlerImpl()
{
	if(m_TaskCondition)
	{
		TaskManager::GetInstance<Tag>().RemoveTaskCondition(m_TaskCondition);
		m_TaskCondition->RemoveTaskManager(&TaskManager::GetInstance<Tag>());
	}
}

// Deprecated ?
template<typename Tag>
bool TaskHandlerImpl<Tag>::IsAttachedToThread()
{
	// Check to see if this handler is attached to this thread; however
	// the handler has never been attached to any thread. Usage is dubious.
	GLF_ASSERT(m_AttachedToThread);

	return m_AttachedToThread == GetCurrentThreadId();
}

// Deprecated ?
template<typename Tag>
void TaskHandlerImpl<Tag>::AttachToThread()
{
	m_AttachedToThread = GetCurrentThreadId();
}

// Deprecated ?
template<typename Tag>
void TaskHandlerImpl<Tag>::DetachFromThread()
{
	m_AttachedToThread = 0;
}

template<typename Tag>
bool TaskHandlerImpl<Tag>::IsEquivalent(TaskHandlerBase* th)
{
	return GetTaskManagerPtr() == th->GetTaskManagerPtr();
}

template<typename Tag>
void TaskHandlerImpl<Tag>::Register()
{
	if(m_RegisteredThreadId)
	{
		TaskDirector::GetInstance().UnregisterHandler(this, m_RegisteredThreadId);
	}

	m_RegisteredThreadId = GetCurrentThreadId();
	TaskDirector::GetInstance().RegisterHandler(this, m_RegisteredThreadId);
}

template<typename Tag>
void TaskHandlerImpl<Tag>::Unregister()
{
	TaskDirector::GetInstance().UnregisterHandler(this, m_RegisteredThreadId);
	m_RegisteredThreadId = 0;
}

template<typename Tag>
const void* TaskHandlerImpl<Tag>::GetTaskManagerPtr()
{
	return &TaskManager::GetInstance<Tag>();
}

template<typename Tag>
TaskHandler<Tag>::TaskHandler(TaskCondition* tc)
	: TaskHandlerImpl<Tag>(tc)
{
}

template<typename Tag>
bool TaskHandler<Tag>::Consume()
{
	return TaskHandlerConsumePolicy<Tag>::Consume();
}

} // end namespace glf

#endif // __GLF_TASK_TASKHANDLER_H_IMPL_INCLUDED__
